package track_formats

import (
	"fmt"
	"strconv"
	"time"

	"github.com/pion/rtp"
	"gogs.smarteye.com/servere/gobvrtp/encoder"
	"gogs.smarteye.com/servere/gobvrtp/track"
)

type AV1Track struct {
	VideoTrack

	LevelIdx *int
	Profile  *int
	Tier     *int

	encoder *encoder.AV1Encoder
	decoder *encoder.AV1Decoder
}

func NewAV1Track() *AV1Track {

	c := &AV1Track{}

	param := c.CtlParma()
	param.SetPayloadType(96)
	param.SetCodec(track.CodecIdAV1)
	param.SetClockRate(90000)
	param.SetOnReadRTPFunc(c.onRTP)

	return c
}

func (c *AV1Track) UnmarshalFormat(ctx *track.FormatContext) error {
	_ = c.VideoTrack.UnmarshalFormat(ctx)
	f := c

	for key, val := range ctx.GetFMTP().KV {
		switch key {
		case "level-idx":
			n, err := strconv.ParseUint(val, 10, 31)
			if err != nil {
				return fmt.Errorf("invalid level-idx: %v", val)
			}

			v2 := int(n)
			f.LevelIdx = &v2

		case "profile":
			n, err := strconv.ParseUint(val, 10, 31)
			if err != nil {
				return fmt.Errorf("invalid profile: %v", val)
			}

			v2 := int(n)
			f.Profile = &v2

		case "tier":
			n, err := strconv.ParseUint(val, 10, 31)
			if err != nil {
				return fmt.Errorf("invalid tier: %v", val)
			}

			v2 := int(n)
			f.Tier = &v2
		}
	}

	return nil
}

// RTPMap implements Format.
func (c *AV1Track) RTPMap() string {
	return "AV1/90000"
}

// FMTP implements Format.
func (c *AV1Track) FMTP() map[string]string {
	fmtp := make(map[string]string)

	f := c

	if f.LevelIdx != nil {
		fmtp["level-idx"] = strconv.FormatInt(int64(*f.LevelIdx), 10)
	}
	if f.Profile != nil {
		fmtp["profile"] = strconv.FormatInt(int64(*f.Profile), 10)
	}
	if f.Tier != nil {
		fmtp["tier"] = strconv.FormatInt(int64(*f.Tier), 10)
	}

	return fmtp
}

func (c *AV1Track) WritePacket(t time.Time, data []byte) error {
	param := c.CtlParma()

	if c.encoder == nil {
		// 初始化编码器
		e := &encoder.AV1Encoder{
			PayloadType:           c.PayloadType(),
			SSRC:                  ToPtr(c.SSRC()),
			InitialSequenceNumber: ToPtr(param.InitialSequenceNumber),
			PayloadMaxSize:        param.PayloadMaxSize,
		}
		_ = e.Init()

		c.encoder = e
	}

	packets, err := c.encoder.Encode([][]byte{data})
	if err != nil {
		return err
	}

	timestamp, _ := c.CtlParma().RtpTimeEncode(t)

	for _, pkt := range packets {
		packet := pkt
		packet.Timestamp = timestamp
		if err = c.WriteRTP(packet); err != nil {
			return err
		}
	}

	return nil
}

func (c *AV1Track) onRTP(_ track.Track, pkt *rtp.Packet) {
	packets, _ := c.Detector(pkt)

	if c.decoder == nil {
		// 初始化解码器
		decoder := &encoder.AV1Decoder{}
		_ = decoder.Init()
		c.decoder = decoder
	}

	for _, packet := range packets {
		if data, err := c.decoder.Decode(packet); err == nil {
			for _, nalu := range data {
				c.onFrame(packet, append([]byte{0, 0, 0, 1}, nalu...))
			}
		}
	}
}

func init() {
	RegisterTrack(track.CodecIdAV1, func() track.Track {
		return NewAV1Track()
	})
}
